package simplevideochat.communication.connection
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.NetStatusEvent;
	import flash.net.NetConnection;
	import simplevideochat.communication.connection.IConnection;
	import simplevideochat.communication.IRoom;
	import flash.net.NetGroup;
	import flash.net.GroupSpecifier;
	
	/**
	 * ...
	 * @author Alexey Ustinov
	 */
	public class P2PConnection implements IConnection 
	{
		
		private var _server:String;
		private var _key:String;
		private var _room:IRoom;
		private var connection:NetConnection;
		private var netGroup:NetGroup;
		private var isConnected:Boolean;
		private var groupspec:GroupSpecifier;
		private var seq:uint = 0;
		private var eventDispatcher:EventDispatcher;
		
		
		public function P2PConnection(server:String, key:String, room:IRoom)
		{
			this.server = server;
			this.key = key;
			this.room = room;
			isConnected = false;
			eventDispatcher = new EventDispatcher();
		}
		
		public function connect():void 
		{
			connection = new NetConnection();
			connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
			connection.connect(server + key);
		}
		
		public function disconnect():void 
		{
			//TODO implement method
		}
		
		public function sendMessage(message:Object):void
		{
			message.sequence = seq;
			message.sender = netGroup.convertPeerIDToGroupAddress(connection.nearID);
			netGroup.post(message);
			seq++;
		}
		
		public function publishMediaStream():void 
		{
			
		}
		
		public function addEventListener(type:String, listener:Function):void
		{
			eventDispatcher.addEventListener(type, listener);
		}
		
		public function removeEventListener(type:String, listener:Function):void 
		{
			eventDispatcher.removeEventListener(type, listener);
		}
		
		
		/*
		 *---------------------------------------------------------------------
		 * Getters/Setters
		 * ---------------------------------------------------------------------
		 */ 
		
		public function get server():String 
		{
			return _server;
		}
		
		public function set server(value:String):void 
		{
			_server = value;
		}
		
		public function get key():String 
		{
			return _key;
		}
		
		public function set key(value:String):void 
		{
			_key = value;
		}
		
		public function get room():IRoom 
		{
			return _room;
		}
		
		public function set room(value:IRoom):void 
		{
			_room = value;
		}
		
		
		/*
		 *---------------------------------------------------------------------
		 * Private
		 * ---------------------------------------------------------------------
		 */ 
		
		private function receiveMessage(message:Object):Object
		{
			if (message.sender)
			{
				if (message.sender != netGroup.convertPeerIDToGroupAddress(connection.nearID))
				{
					var event:ConnectionEvent = new ConnectionEvent(message.type);
					event.connectionData = message;
					eventDispatcher.dispatchEvent(event);
					return message;
				}
			}
			return null;
		}
		
		private function netStatusHandler(e:NetStatusEvent):void 
		{
			trace(e.info.code);
			switch(e.info.code)
			{
				case "NetConnection.Connect.Success":
					setupGroup();
					break;
					
				case "NetGroup.Connect.Success":
					isConnected = true;
					eventDispatcher.dispatchEvent(new ConnectionEvent(ConnectionEvent.CONNECTED));
					break;
					
				case "NetGroup.Posting.Notify":
					receiveMessage(e.info.message);
					break;
					
				case "NetGroup.Connect.Failed":
				case "NetGroup.Connect.Rejected":
				case "NetConnection.Connect.Rejected":
				case "NetConnection.Connect.Failed":
					eventDispatcher.dispatchEvent(new ConnectionEvent(ConnectionEvent.ERROR));
					break;
			}
		}
		
		private function setupGroup():void
		{
			groupspec = new GroupSpecifier(room.roomID);
			groupspec.serverChannelEnabled = true;
			groupspec.postingEnabled = true;
			groupspec.multicastEnabled = true;
			groupspec.ipMulticastMemberUpdatesEnabled = true;
			
			netGroup = new NetGroup(connection, groupspec.groupspecWithAuthorizations());
			netGroup.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
		}
		
	}

}